#!usr/bin/env python3
import struct

#封包和解包工具
'''
最终可以封包和解包:
0x11 + 封包长度 + 协议号 + 数据 + 0x22 ;这样的数据格式 (已经完成 2016年11月30日15:05:59)
其中:0x11(h) + 封包长度(I) + 协议号(i) 是包头;数据 是包体;0x22(h)是包尾
'''
#还需要完成拆包粘包 
#相关理论和教程:
#http://blog.csdn.net/yazhouren/article/details/46797291
#http://blog.csdn.net/yannanxiu/article/details/52096465  #TCP Socket的粘包和分包的处理

dataFmt={
    1001:'ssbi',
    1002:'s',
}

BEGIN = 0x11
END   = 0x22

#获取包头的长度
def getHeaderSize():
    headerSize = struct.calcsize('hII')
    return headerSize


#获取格式
def getFmt():
    pass

#封包;
#cmdid 协议号
#data(list)数据
#return data,fmt
def packData(cmdid,data):
    fmt = dataFmt[cmdid]    
    fmtStrRes = []
    fixStrDict = {}
    idx = 0
    for k in fmt:
        if k=='n':
            fmtStrRes.append('h')
        elif k=='b':
            fmtStrRes.append('h')
        elif k=='u':
            fmtStrRes.append('I')
        elif k=='i':
            fmtStrRes.append('i')
        elif k=='s':
            strLen = len(data[idx]) #获取字符串数据的长度            
            fixStrDict[idx] = strLen
            sfmt = 'h'+str(strLen)+'s'
            print("packData --- idx,strLen,sfmt",idx,strLen,sfmt)
            fmtStrRes.append(sfmt)
        idx +=1
    #print('插入长度前data',data)
    #把字符串的长度插入到data中
    if len(fixStrDict)>0:
        idx = 0
        for k,v in fixStrDict.items():
            data.insert(k+idx,v)
            idx+=1
    #print('插入长度后data',data)
    data.insert(0,BEGIN) #插入数据的开始标识    
    data.append(END) #插入数据的结束标识
    beginEnd = 'h' #数据开始和结束的格式
    packLenAndProtol = 'I' #包的长度和协议号类型; 无符号整形
    fmt = "!"+beginEnd+packLenAndProtol*2+''.join(fmtStrRes)+beginEnd
    data.insert(1,struct.calcsize(fmt)) #插入封包长度
    data.insert(2,cmdid) #插入协议号    
    #print('fmt',fmt)
    res = struct.pack(fmt,*data)
    #print('res',res,type(res))
    return res,fmt
    

#解包    
def unpackData(data,offset = 0):    
    resData = []    
    resData.append(struct.unpack_from('!h',data,offset=offset)[0]) #读取开始标识
    offset+=2
    
    resData.append(struct.unpack_from('!I',data,offset=offset)[0]) #读取包的长度
    offset+=4
    
    cmdid = struct.unpack_from('!I',data,offset=offset)[0]
    resData.append(cmdid) #读取协议号
    offset+=4
    print('unpackData前三条数据 resData=',resData)
    #return
    fmt = dataFmt[cmdid]    
    fmtStrRes = []
    fixStrDict = {}
    idx = 0    
    for k in fmt: #分析和读取协议数据
        if k=='n':
            resData.append(struct.unpack_from('!h',data,offset=offset)[0])
            offset+=2
        elif k=='b':
            datab = struct.unpack_from('!h',data,offset=offset)[0]            
            resData.append(datab)
            offset+=2
        elif k=='u':
            resData.append(struct.unpack_from('!I',data,offset=offset)[0])
            offset+=4
        elif k=='i':
            datai = struct.unpack_from('!i',data,offset=offset)[0]            
            resData.append(datai)
            offset+=4
        elif k=='s':          
            strNum = struct.unpack_from('!h',data,offset=offset)[0] #先读取字符串的长度           
            offset +=2           
            resData.append(strNum)
            tfmt=str(strNum)+'s'
            print("unpackData ------最闪亮的※※※※",'offset',offset,"strNum",strNum,'idx',idx)
            rd = struct.unpack_from(tfmt,data,offset=offset)            
            resData.append(rd[0])
            offset+=strNum                       
        idx+=1
            
    resData.append(struct.unpack_from('!h',data,offset=offset)[0]) #读取结束标识
    offset+=2
    #print('unpackData',resData)
    return resData

'''
longStr = 'ServerSock'*500
sendData = ['Hello'.encode('utf-8'),longStr.encode('utf-8'),50,999888]
data,fmt=packData(1001,sendData)
#print('正确解包=',struct.unpack(fmt,data))
print("自定义的解包",unpackData(data))

struct.calcsize(fmt)
print(int('0x11', 16),int('0x22', 16)) #16进制转换成10进制
'''



